home *** CD-ROM | disk | FTP | other *** search
/ Nautilus 1992 July / Nautilus-3-8 / Nautilus-3-8.bin / Tools & Utilities / Techy Stuff / Development Environments ƒ / Perl 4.0.2 ƒ / form.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-05  |  9.0 KB  |  392 lines

  1. /* $RCSfile: form.c,v $$Revision: 4.0.1.2 $$Date: 91/11/05 17:18:43 $
  2.  *
  3.  *    Copyright (c) 1991, Larry Wall
  4.  *
  5.  *    You may distribute under the terms of either the GNU General Public
  6.  *    License or the Artistic License, as specified in the README file.
  7.  *
  8.  * $Log:    form.c,v $
  9.  * Revision 4.0.1.2  91/11/05  17:18:43  lwall
  10.  * patch11: formats didn't fill their fields as well as they could
  11.  * patch11: ^ fields chopped hyphens on line break
  12.  * patch11: # fields could write outside allocated memory
  13.  * 
  14.  * Revision 4.0.1.1  91/06/07  11:07:59  lwall
  15.  * patch4: new copyright notice
  16.  * patch4: default top-of-form format is now FILEHANDLE_TOP
  17.  * 
  18.  * Revision 4.0  91/03/20  01:19:23  lwall
  19.  * 4.0 baseline.
  20.  * 
  21.  */
  22.  
  23. #include "EXTERN.h"
  24. #include "perl.h"
  25.  
  26. /* Forms stuff */
  27.  
  28. void
  29. form_parseargs(fcmd)
  30. register FCMD *fcmd;
  31. {
  32.     register int i;
  33.     register ARG *arg;
  34.     register int items;
  35.     STR *str;
  36.     ARG *parselist();
  37.     line_t oldline = curcmd->c_line;
  38.     int oldsave = savestack->ary_fill;
  39.  
  40.     str = fcmd->f_unparsed;
  41.     curcmd->c_line = fcmd->f_line;
  42.     fcmd->f_unparsed = Nullstr;
  43. #ifndef macintosh
  44.     (void)savehptr(&curstash);
  45. #else
  46.     savehptr(&curstash);
  47. #endif
  48.     curstash = str->str_u.str_hash;
  49.     arg = parselist(str);
  50.     restorelist(oldsave);
  51.  
  52.     items = arg->arg_len - 1;    /* ignore $$ on end */
  53.     for (i = 1; i <= items; i++) {
  54.     if (!fcmd || fcmd->f_type == F_NULL)
  55.         fatal("Too many field values");
  56.     dehoist(arg,i);
  57.     fcmd->f_expr = make_op(O_ITEM,1,
  58.       arg[i].arg_ptr.arg_arg,Nullarg,Nullarg);
  59.     if (fcmd->f_flags & FC_CHOP) {
  60.         if ((fcmd->f_expr[1].arg_type & A_MASK) == A_STAB)
  61.         fcmd->f_expr[1].arg_type = A_LVAL;
  62.         else if ((fcmd->f_expr[1].arg_type & A_MASK) == A_EXPR)
  63.         fcmd->f_expr[1].arg_type = A_LEXPR;
  64.         else
  65.         fatal("^ field requires scalar lvalue");
  66.     }
  67.     fcmd = fcmd->f_next;
  68.     }
  69.     if (fcmd && fcmd->f_type)
  70.     fatal("Not enough field values");
  71.     curcmd->c_line = oldline;
  72.     Safefree(arg);
  73.     str_free(str);
  74. }
  75.  
  76. int newsize;
  77.  
  78. #define CHKLEN(allow) \
  79. newsize = (d - orec->o_str) + (allow); \
  80. if (newsize >= curlen) { \
  81.     curlen = d - orec->o_str; \
  82.     GROWSTR(&orec->o_str,&orec->o_len,orec->o_len + (allow)); \
  83.     d = orec->o_str + curlen;    /* in case it moves */ \
  84.     curlen = orec->o_len - 2; \
  85. }
  86.  
  87. format(orec,fcmd,sp)
  88. register struct outrec *orec;
  89. register FCMD *fcmd;
  90. int sp;
  91. {
  92.     register char *d = orec->o_str;
  93.     register char *s;
  94.     register int curlen = orec->o_len - 2;
  95.     register int size;
  96.     FCMD *nextfcmd;
  97.     FCMD *linebeg = fcmd;
  98.     char tmpchar;
  99.     char *t;
  100.     CMD mycmd;
  101.     STR *str;
  102.     char *chophere;
  103.  
  104.     mycmd.c_type = C_NULL;
  105.     orec->o_lines = 0;
  106.     for (; fcmd; fcmd = nextfcmd) {
  107.     nextfcmd = fcmd->f_next;
  108.     CHKLEN(fcmd->f_presize);
  109.     /*SUPPRESS 560*/
  110.     if (s = fcmd->f_pre) {
  111.         while (*s) {
  112.         if (*s == '\n') {
  113.             while (d > orec->o_str && (d[-1] == ' ' || d[-1] == '\t'))
  114.             d--;
  115.             if (fcmd->f_flags & FC_NOBLANK) {
  116.             if (d == orec->o_str || d[-1] == '\n') {
  117.                 orec->o_lines--;    /* don't print blank line */
  118.                 linebeg = fcmd->f_next;
  119.                 break;
  120.             }
  121.             else if (fcmd->f_flags & FC_REPEAT)
  122.                 nextfcmd = linebeg;
  123.             else
  124.                 linebeg = fcmd->f_next;
  125.             }
  126.             else
  127.             linebeg = fcmd->f_next;
  128.         }
  129.         *d++ = *s++;
  130.         }
  131.     }
  132.     if (fcmd->f_unparsed)
  133.         form_parseargs(fcmd);
  134.     switch (fcmd->f_type) {
  135.     case F_NULL:
  136.         orec->o_lines++;
  137.         break;
  138.     case F_LEFT:
  139.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  140.         str = stack->ary_array[sp+1];
  141.         s = str_get(str);
  142.         size = fcmd->f_size;
  143.         CHKLEN(size);
  144.         chophere = Nullch;
  145.         while (size && *s && *s != '\n') {
  146.         if (*s == '\t')
  147.             *s = ' ';
  148.         size--;
  149.         if (*s && index(chopset,(*d++ = *s++)))
  150.             chophere = s;
  151.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  152.             *s = ' ';
  153.         }
  154.         if (size || !*s)
  155.         chophere = s;
  156.         else if (chophere && chophere < s && *s && index(chopset,*s))
  157.         chophere = s;
  158.         if (fcmd->f_flags & FC_CHOP) {
  159.         if (!chophere)
  160.             chophere = s;
  161.         size += (s - chophere);
  162.         d -= (s - chophere);
  163.         if (fcmd->f_flags & FC_MORE &&
  164.           *chophere && strNE(chophere,"\n")) {
  165.             while (size < 3) {
  166.             d--;
  167.             size++;
  168.             }
  169.             while (d[-1] == ' ' && size < fcmd->f_size) {
  170.             d--;
  171.             size++;
  172.             }
  173.             *d++ = '.';
  174.             *d++ = '.';
  175.             *d++ = '.';
  176.             size -= 3;
  177.         }
  178.         while (*chophere && index(chopset,*chophere)
  179.           && isSPACE(*chophere))
  180.             chophere++;
  181.         str_chop(str,chophere);
  182.         }
  183.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  184.         size = 0;            /* no spaces before newline */
  185.         while (size) {
  186.         size--;
  187.         *d++ = ' ';
  188.         }
  189.         break;
  190.     case F_RIGHT:
  191.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  192.         str = stack->ary_array[sp+1];
  193.         t = s = str_get(str);
  194.         size = fcmd->f_size;
  195.         CHKLEN(size);
  196.         chophere = Nullch;
  197.         while (size && *s && *s != '\n') {
  198.         if (*s == '\t')
  199.             *s = ' ';
  200.         size--;
  201.         if (*s && index(chopset,*s++))
  202.             chophere = s;
  203.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  204.             *s = ' ';
  205.         }
  206.         if (size || !*s)
  207.         chophere = s;
  208.         else if (chophere && chophere < s && *s && index(chopset,*s))
  209.         chophere = s;
  210.         if (fcmd->f_flags & FC_CHOP) {
  211.         if (!chophere)
  212.             chophere = s;
  213.         size += (s - chophere);
  214.         s = chophere;
  215.         while (*chophere && index(chopset,*chophere)
  216.           && isSPACE(*chophere))
  217.             chophere++;
  218.         }
  219.         tmpchar = *s;
  220.         *s = '\0';
  221.         while (size) {
  222.         size--;
  223.         *d++ = ' ';
  224.         }
  225.         size = s - t;
  226.         (void)bcopy(t,d,size);
  227.         d += size;
  228.         *s = tmpchar;
  229.         if (fcmd->f_flags & FC_CHOP)
  230.         str_chop(str,chophere);
  231.         break;
  232.     case F_CENTER: {
  233.         int halfsize;
  234.  
  235.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  236.         str = stack->ary_array[sp+1];
  237.         t = s = str_get(str);
  238.         size = fcmd->f_size;
  239.         CHKLEN(size);
  240.         chophere = Nullch;
  241.         while (size && *s && *s != '\n') {
  242.         if (*s == '\t')
  243.             *s = ' ';
  244.         size--;
  245.         if (*s && index(chopset,*s++))
  246.             chophere = s;
  247.         if (*s == '\n' && (fcmd->f_flags & FC_CHOP))
  248.             *s = ' ';
  249.         }
  250.         if (size || !*s)
  251.         chophere = s;
  252.         else if (chophere && chophere < s && *s && index(chopset,*s))
  253.         chophere = s;
  254.         if (fcmd->f_flags & FC_CHOP) {
  255.         if (!chophere)
  256.             chophere = s;
  257.         size += (s - chophere);
  258.         s = chophere;
  259.         while (*chophere && index(chopset,*chophere)
  260.           && isSPACE(*chophere))
  261.             chophere++;
  262.         }
  263.         tmpchar = *s;
  264.         *s = '\0';
  265.         halfsize = size / 2;
  266.         while (size > halfsize) {
  267.         size--;
  268.         *d++ = ' ';
  269.         }
  270.         size = s - t;
  271.         (void)bcopy(t,d,size);
  272.         d += size;
  273.         *s = tmpchar;
  274.         if (fcmd->f_next && fcmd->f_next->f_pre[0] == '\n')
  275.         size = 0;            /* no spaces before newline */
  276.         else
  277.         size = halfsize;
  278.         while (size) {
  279.         size--;
  280.         *d++ = ' ';
  281.         }
  282.         if (fcmd->f_flags & FC_CHOP)
  283.         str_chop(str,chophere);
  284.         break;
  285.     }
  286.     case F_LINES:
  287.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  288.         str = stack->ary_array[sp+1];
  289.         s = str_get(str);
  290.         size = str_len(str);
  291.         CHKLEN(size+1);
  292.         orec->o_lines += countlines(s,size) - 1;
  293.         (void)bcopy(s,d,size);
  294.         d += size;
  295.         if (size && s[size-1] != '\n') {
  296.         *d++ = '\n';
  297.         orec->o_lines++;
  298.         }
  299.         linebeg = fcmd->f_next;
  300.         break;
  301.     case F_DECIMAL: {
  302.         double value;
  303.  
  304.         (void)eval(fcmd->f_expr,G_SCALAR,sp);
  305.         str = stack->ary_array[sp+1];
  306.         size = fcmd->f_size;
  307.         CHKLEN(size+1);
  308.         /* If the field is marked with ^ and the value is undefined,
  309.            blank it out. */
  310.         if ((fcmd->f_flags & FC_CHOP) && !str->str_pok && !str->str_nok) {
  311.         while (size) {
  312.             size--;
  313.             *d++ = ' ';
  314.         }
  315.         break;
  316.         }
  317.         value = str_gnum(str);
  318.         if (fcmd->f_flags & FC_DP) {
  319.         sprintf(d, "%#*.*f", size, fcmd->f_decimals, value);
  320.         } else {
  321.         sprintf(d, "%*.0f", size, value);
  322.         }
  323.         d += size;
  324.         break;
  325.     }
  326.     }
  327.     }
  328.     CHKLEN(1);
  329.     *d++ = '\0';
  330. }
  331.  
  332. countlines(s,size)
  333. register char *s;
  334. register int size;
  335. {
  336.     register int count = 0;
  337.  
  338.     while (size--) {
  339.     if (*s++ == '\n')
  340.         count++;
  341.     }
  342.     return count;
  343. }
  344.  
  345. do_write(orec,stab,sp)
  346. struct outrec *orec;
  347. STAB *stab;
  348. int sp;
  349. {
  350.     register STIO *stio = stab_io(stab);
  351.     FILE *ofp = stio->ofp;
  352.  
  353. #ifdef DEBUGGING
  354.     if (debug & 256)
  355.     fprintf(stderr,"left=%ld, todo=%ld\n",
  356.       (long)stio->lines_left, (long)orec->o_lines);
  357. #endif
  358.     if (stio->lines_left < orec->o_lines) {
  359.     if (!stio->top_stab) {
  360.         STAB *topstab;
  361.         char tmpbuf[256];
  362.  
  363.         if (!stio->top_name) {
  364.         if (!stio->fmt_name)
  365.             stio->fmt_name = savestr(stab_name(stab));
  366.         sprintf(tmpbuf, "%s_TOP", stio->fmt_name);
  367.         topstab = stabent(tmpbuf,FALSE);
  368.         if (topstab && stab_form(topstab))
  369.             stio->top_name = savestr(tmpbuf);
  370.         else
  371.             stio->top_name = savestr("top");
  372.         }
  373.         topstab = stabent(stio->top_name,FALSE);
  374.         if (!topstab || !stab_form(topstab)) {
  375.         stio->lines_left = 100000000;
  376.         goto forget_top;
  377.         }
  378.         stio->top_stab = topstab;
  379.     }
  380.     if (stio->lines_left >= 0 && stio->page > 0)
  381.         (void)putc('\f',ofp);
  382.     stio->lines_left = stio->page_len;
  383.     stio->page++;
  384.     format(&toprec,stab_form(stio->top_stab),sp);
  385.     fputs(toprec.o_str,ofp);
  386.     stio->lines_left -= toprec.o_lines;
  387.     }
  388.   forget_top:
  389.     fputs(orec->o_str,ofp);
  390.     stio->lines_left -= orec->o_lines;
  391. }
  392.